package com.tangsm.spring.mvc.mybatis.controller;

import com.tangsm.spring.mvc.mybatis.domain.dto.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;

/**
 * 上传文件示例
 */
@Controller
public class UploadController {
    private Logger log = LoggerFactory.getLogger(UploadController.class);

    private static final String UPLOAD_DIR = "D:\\test\\upload\\";
    private static final long MAX_FILE_SISE = 1000000;

    /**
     * 单文件上传（form提交，返回特定页面）
     *
     * @param file 上传文件
     * @return View页面模型
     */
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public ModelAndView upload(@RequestParam("file") MultipartFile file) {
        if (!file.isEmpty()) {
            //获取文件类型
            String contentType = file.getContentType();
            if (!contentType.equals("")) {
                //可以对文件类型进行检查
            }
            //获取input域的name属性
            String name = file.getName();
            //获取文件名，带扩展名
            String originFileName = file.getOriginalFilename();
            //获取文件扩展名
            String extension = originFileName.substring(originFileName.lastIndexOf("."));
            //获取文件大小，单位字节
            long site = file.getSize();
            if (site > MAX_FILE_SISE) {
                //可以对文件大小进行检查
            }
            //构造文件上传后的文件绝对路径，这里取系统时间戳＋文件名作为文件名
            //不推荐这么写，这里只是举例子，这么写会有并发问题
            //应该采用一定的算法生成独一无二的的文件名
            String fileName = UPLOAD_DIR + String.valueOf(System.currentTimeMillis()) + extension;
            try {
                file.transferTo(new File(fileName));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        ModelAndView mv = new ModelAndView();
        mv.addObject("message", "上传成功");
        mv.setViewName("book/book-main");
        return mv;
    }

    /**
     * 批量上传（form提交，返回特定页面）
     *
     * @param request 请求信息
     * @return View页面模型
     * @throws IllegalStateException 请求异常
     * @throws IOException           IO异常
     */
    @RequestMapping(value = "/uploadBatch")
    public ModelAndView uploadBatch(HttpServletRequest request) throws IllegalStateException, IOException {
        // 创建一个通用的多部分解析器
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
                request.getSession().getServletContext());
        // 判断 request 是否有文件上传,即多部分请求
        if (multipartResolver.isMultipart(request)) {
            // 转换成多部分request
            MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
            // 取得request中的所有文件名
            Iterator<String> iter = multiRequest.getFileNames();
            while (iter.hasNext()) {
                // 记录上传过程起始时的时间，用来计算上传时间
                int pre = (int) System.currentTimeMillis();
                // 取得上传文件
                MultipartFile file = multiRequest.getFile(iter.next());
                if (file != null) {
                    // 取得当前上传文件的文件名称
                    String myFileName = file.getOriginalFilename();
                    // 如果名称不为“”,说明该文件存在，否则说明该文件不存在
                    if (!"".equals(myFileName)) {
                        // 重命名上传后的文件名
                        String fileName = "demoUpload" + file.getOriginalFilename();
                        // 定义上传路径
                        String path = UPLOAD_DIR + fileName;
                        File localFile = new File(path);
                        file.transferTo(localFile);
                    }
                    // 记录上传该文件后的时间
                    int finaltime = (int) System.currentTimeMillis();
                    log.info("[{}]上传耗时：{}", myFileName, (finaltime - pre));
                }
            }
        }
        ModelAndView mv = new ModelAndView();
        mv.addObject("message", "上传成功");
        mv.setViewName("book/book-main");
        return mv;
    }

    /**
     * ajx上传
     *
     * @param request 请求信息
     * @param loginName 登录用户名
     * @return 提示信息
     * @throws IOException
     */
    @RequestMapping("ajxUpload")
    @ResponseBody
    public Result<String> fileupload(HttpServletRequest request, String loginName) throws IOException {
        StringBuffer fileNames = new StringBuffer();
        //获取解析器
        CommonsMultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext());

        //判断是否是文件
        if (resolver.isMultipart(request)) {
            //进行转换
            MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) (request);
            //获取所有文件名称
            Iterator<String> it = multiRequest.getFileNames();
            while (it.hasNext()) {
                //根据文件名称取文件
                MultipartFile file = multiRequest.getFile(it.next());
                String fileName = file.getOriginalFilename();
                if (!"".equals(fileName)) {
                    String localPath = UPLOAD_DIR + System.currentTimeMillis() + "-" + fileName;
                    //创建一个新的文件对象，创建时需要一个参数，参数是文件所需要保存的位置
                    File newFile = new File(localPath);
                    if (newFile.getParentFile() != null || !newFile.getParentFile().isDirectory()) {
                        // 创建父文件夹
                        newFile.getParentFile().mkdirs();
                    }
                    //上传的文件写入到指定的文件中
                    file.transferTo(newFile);

                    if(fileNames.length() != 0) {
                        fileNames.append(",").append(fileName);
                    } else {
                        fileNames.append(fileName);
                    }
                }
            }
        }

        return new Result<>(true, String.format("用户[%s]，上传文件[%s]成功", loginName, fileNames));
    }
}
